package util;

import java.util.*;
import bll.*;

public class TreeUtil {

	public static <T extends ITreeNode> List<T> organizeTree(List<T> nodes) {
		List<T> orderedNodes = new ArrayList<T>();

		List<T> roots = new ArrayList<T>();

		for (T node : nodes) {
			if (node.getIdParent() <= 0) {
				roots.add(node);
				// node.setLevel(0);
			} else {
				ITreeNode parent = searchNode(nodes, node.getIdParent());
				if (parent != null) {
					node.setParent(parent);
					parent.addChildNode(node);
					parent.setIsGroup(true);
				} else {
					roots.add(node);
				}
			}
		}

		Collections.sort(roots);

		for (T root : roots) {
			setLevel(root, 0);
		}

		for (T root : roots) {
			addRecursive(orderedNodes, root);
		}

		// add orphaned nodes
		for (T node : nodes) {
			if (!node.getAddedToTree()) {
				orderedNodes.add(node);
			}
		}

		return orderedNodes;
	}

	private static <T extends ITreeNode> void setLevel(T node, int level) {
		node.setLevel(level);
		for (ITreeNode child : node.getChildNodes()) {
			setLevel(child, level + 1);
		}
	}

	private static <T extends ITreeNode> void addRecursive(List<T> orderedNodes, T root) {

		orderedNodes.add(root);
		root.setAddedToTree(true);

		List<ITreeNode> childNodes = root.getChildNodes();
		Collections.sort(childNodes);

		for (int i = 0; i < childNodes.size(); i++) {
			T node = (T) childNodes.get(i);
			addRecursive(orderedNodes, node);
		}
	}

	public static <T extends ITreeNode> ITreeNode searchNode(List<T> nodes, int id) {
		for (T node : nodes) {
			if (node.getId() == id) {
				return node;
			}
		}
		return null;
	}

}
